package com.itheima.d1_create;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

/**
 * 目标：学会线程创建方式三
 * 通过实现 Callable接口 结合 FutureTask 完成
 * 1. 创建 Callable 接口的实现类，并实现 call() 方法，该 call() 方法将作为线程执行体，并且有返回值。
 *
 * 2. 创建 Callable 实现类的实例，使用 FutureTask 类来包装 Callable 对象，该 FutureTask 对象封装了该 Callable 对象的 call() 方法的返回值。
 *
 * 3. 使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程。
 *
 * 4. 调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值。
 */


public class ThreadDemo3 {
    public static void main(String[] args) {
    //3.创建Callable任务对象
    Callable<String> call = new MyCallable(100);
    //4.把Callable任务对象 交给 FutureTask 对象
    //  FutureTask对象作用1：是Runnable的对象（实现了Runnable接口），就可以交给Thread了
    //  FutureTask对象作用2：可以在线程执行完毕后通过调用get方法得到线程执行完成结果
        FutureTask<String> f1 = new FutureTask<>(call);
    // 5.交给线程处理
        Thread t1 = new Thread(f1);
    // 6.启动线程
    t1.start();



        Callable<String> call2 = new MyCallable(200);
        FutureTask<String> f2 = new FutureTask<>(call2);
        Thread t2 = new Thread(f2);
        t2.start();

        try {
            //如果f1任务没有执行完，这里的代码会等待，直到线程1跑完才提取结果
            String rs1 = f1.get();//get方法的优点可以等上面两个线程执行完再执行
            System.out.printf("第一个结果" + rs1);
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            //如果f2任务没有执行完，这里的代码会等待，直到线程2跑完才提取结果
            String rs2 = f2.get();//get方法的优点可以等上面两个线程执行完再执行
            System.out.printf("第二个结果" + rs2);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

//1.定义一个任务类 实现Callable接口 一个申明线程任务执行完毕后的结果的数据类型

class MyCallable implements Callable<String>{
    private int n;
    public MyCallable(int n) {
        this.n = n;
    }

//2.重写call方法（任务方法）
    @Override
    public String call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= n; i++) {
            sum += i;
        }
        return "子线程执行结果是：" +sum;
    }
}